﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Forest.Cat.Domain.Entities;
using Forest.Core;
using Forest.Core.Caching;
using Forest.Core.Data;
using Forest.Core.Events;
using Forest.Cat.Domain.Shared;
using Forest.Cat.Domain.Configuration;

namespace Forest.Cat.Domain.Services.Compnaies {
    public class CompanyService : ICompanyService {
        #region Constants
        private const string COMPANY_BY_ID_KEY = "company.id-{0}";
        private const string COMPANY_PATTERN_KEY = "company.";
        #endregion

        #region Fields
        private readonly IRepository<Company> _companyRepository;
        private readonly IRepository<JobPosition> _jobPositionRepository;
        private readonly IRepository<CompanyTemplate> _companyTemplateRepository;
        private readonly ILovService _lovService;
        private readonly ICacheManager _cacheManager;
        private readonly IEventPublisher _eventPublisher;
        #endregion

        #region Ctor
        public CompanyService(IRepository<Company> companyRepository,
            IRepository<JobPosition> jobPositionRepository,
            IRepository<CompanyTemplate> companyTemplateRepository,
            ICacheManager cacheManager,
            IEventPublisher eventPublisher,
            ILovService lovService) {
            _companyRepository = companyRepository;
            _jobPositionRepository = jobPositionRepository;
            _companyTemplateRepository = companyTemplateRepository;
            _cacheManager = cacheManager;
            _eventPublisher = eventPublisher;
            _lovService = lovService;
        }
        #endregion

        #region Base Methods
        public virtual void DeleteCompany(Company company) {
            if (company == null)
                throw new ArgumentNullException("Company");

            _companyRepository.Delete(company);
            _cacheManager.RemoveByPattern(COMPANY_PATTERN_KEY);
            _eventPublisher.EntityDeleted(company);
        }

        public Company GetCompanyById(Guid companyId) {
            if (companyId == Guid.Empty)
                return null;
            string key = string.Format(COMPANY_BY_ID_KEY, companyId);

            return _cacheManager.Get(key, () => {
                var cl = _companyRepository.GetById(companyId);
                return cl;
            });
        }

        public virtual IPagedList<Company> GetAllCompanys(int pageIndex, int pageSize) {
            var query = _companyRepository.Table;
            query = query.OrderBy(w => w.Id);
            var items = new PagedList<Company>(query, pageIndex, pageSize);
            return items;
        }

        public virtual void InsertCompany(Company company) {
            if (company == null)
                throw new ArgumentNullException("Company");
            _companyRepository.Insert(company);
            _cacheManager.RemoveByPattern(COMPANY_PATTERN_KEY);
            _eventPublisher.EntityInserted(company);
        }

        public virtual void UpdateCompany(Company company) {
            if (company == null)
                throw new ArgumentNullException("Company");
            _companyRepository.Update(company);
            _cacheManager.RemoveByPattern(COMPANY_PATTERN_KEY);
            _eventPublisher.EntityUpdated(company);
        }
        #endregion

        #region Extend Methods
        public string GetCompanyNameById(Guid id) {
            return _companyRepository.Table.Where(x => x.Id.Equals(id)).Select(x => x.CompanyName).FirstOrDefault();
        }

        public IList<Company> GetShieldedCompany(string name) {
            return _companyRepository.Table.Where(i => i.CompanyName.Contains(name)).ToList();
        }

        #region 会员招聘

        public IQueryable<Company> GetVIPMemberRecruitingList(int topCount, int skipCount = 0, String lovCondition = null) {
            var status = (int)Status.Publish;
            var currentDate = DateTime.Now.Date;

            IQueryable<Company> companyList = _companyRepository.Table.Where(x => x.Status == status &&
                        x.ExpiryDate >= currentDate &&
                        x.ServiceType == 120102)
                                                                        .OrderByDescending(x => x.DailySigned)
                                                                        .Skip(skipCount)
                                                                        .Take(topCount);
            if (!String.IsNullOrWhiteSpace(lovCondition)) {
                companyList = AddLovCondition(companyList, lovCondition);
            }
            return companyList;
        }

        public IQueryable<Company> GetMemberRecruitingList(int topCount, int skipCount = 0, String lovCondition = null) {
            var status = (int)Status.Publish;
            var currentDate = DateTime.Now.Date;

            IQueryable<Company> companyList = _companyRepository.Table.Where(x => x.Status == status && x.ExpiryDate >= currentDate)
                                                                        .OrderByDescending(x => x.DailySigned)
                                                                        .Skip(skipCount)
                                                                        .Take(topCount);
            if (!String.IsNullOrWhiteSpace(lovCondition)) {
                companyList = AddLovCondition(companyList, lovCondition);
            }
            return companyList;
        }

        /// <summary>
        /// 在职位结果集上附加Lov类型的查询
        /// </summary>
        /// <param name="jobList"></param>
        /// <param name="lovType"></param>
        /// <param name="lovValue"></param>
        /// <returns></returns>
        private IQueryable<Company> AddLovCondition(IQueryable<Company> companyList, String lovCondition) {
            var lovConditionList = lovCondition.Split('|').Where(x => !String.IsNullOrWhiteSpace(x)).ToList();
            lovConditionList.ForEach(x => {
                var lovType = (LovType)Enum.Parse(typeof(LovType), x.Split('-')[0]);
                var lovValue = int.Parse(x.Split('-')[1]);
                switch (lovType) {
                    //公司性质
                    case LovType.CompanyType:
                        companyList = companyList.Where(item => item.CompanyType.HasValue && item.CompanyType.Value.Equals(lovValue));
                        break;
                }
            });
            return companyList;
        }

        #endregion

        #region 获取公司模板
        public CompanyTemplate GetTemplate(Guid templateId) {
            return _companyTemplateRepository.Table.FirstOrDefault(x => x.Id.Equals(templateId));
        }
        #endregion

        #region 获取职位相关Lov列表
        /// <summary>
        /// 获取职位相关Lov列表
        /// </summary>
        /// <param name="jobTitle"></param>
        /// <param name="companyName"></param>
        /// <param name="lovType"></param>
        /// <returns></returns>
        public IList<LovInfoForSearchListView> GetLovInfoList(LovType lovType, int topCount, int skipCount, String lovCondition) {
            var companyList = GetMemberRecruitingList(topCount, skipCount, lovCondition);
            return DoGetLovInfoList(companyList, lovType);
        }

        /// <summary>
        /// 执行获取Lov信息的操作
        /// </summary>
        /// <param name="companyList"></param>
        /// <param name="lovType"></param>
        /// <returns></returns>
        private IList<LovInfoForSearchListView> DoGetLovInfoList(IQueryable<Company> companyList, LovType lovType) {
            List<LovInfoForSearchListView> groupList = null;
            IEnumerable<LovInfoForSearchListView> tempList = null;
            switch (lovType) {
                //公司性质
                case LovType.CompanyType:
                    tempList = companyList.Where(i => i.CompanyType.HasValue).
                        GroupBy(i => i.CompanyType).Select(i => new LovInfoForSearchListView { Value = i.Key.Value, Total = i.Count() });
                    break;
            }
            groupList = tempList.ToList();
            groupList.ForEach(item => {
                var lov = _lovService.GetAll().FirstOrDefault(i => i.Value.Equals(item.Value));
                if (lov != null) {
                    item.Name = lov.Name;
                    item.ParentId = lov.ParentId;
                }
            });
            return groupList;
        }
        #endregion

        #endregion
    }
}
